#include <string>
#include <vector>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include "ContentType.h"

#define foreach BOOST_FOREACH

using namespace kc_sf;
namespace ba = boost::algorithm;

// --------------------------------------------------------------- //

ContentType::ContentType(
	const std::string &_type,
	const std::string &_subtype,
	const std::string &parameters_string )
: ct_type( _type ),
  ct_subtype( _subtype )
{
	extractParameters( parameters_string );
}

// --------------------------------------------------------------- //

bool ContentType::operator ==( const ContentType &ct ) const
{
	bool success = ba::iequals( this->ct_type, ct.ct_type );
	if( success )
		success = ba::iequals( this->ct_subtype, ct.ct_subtype );

	return success;
}

// --------------------------------------------------------------- //

bool ContentType::operator !=( const ContentType &ct ) const
{
	return !(*this == ct );
}

// --------------------------------------------------------------- //

bool ContentType::isBodyText() const
{
	return ba::iequals( ct_type, "text" )
		&& ( ba::iequals( ct_subtype, "plain" ) || ba::iequals( ct_subtype, "html" ) );
}

// --------------------------------------------------------------- //

void ContentType::extractParameters( const std::string &param_unparsed_string )
{
	std::string copy = param_unparsed_string;

	char chars[] = "\r\n";
	for (size_t i = 0; i < sizeof( chars ); ++i)
	{
		copy.erase( std::remove( copy.begin(), copy.end(), chars[i] ), copy.end() );
	}

	std::vector <std::string> parameters;
	boost::split( parameters, copy, boost::is_any_of( ";" ) );

	foreach( std::string parameter, parameters )
	{
		std::vector <std::string> key_value;
		boost::split( key_value, parameter, boost::is_any_of( "  \t=\"" ) );

		key_value.erase( std::remove( key_value.begin(), key_value.end(), "" ), key_value.end() );

		if( key_value.size() >= 2 )
		{
			ct_parameters[ boost::to_lower_copy( key_value[ 0 ] ) ] = key_value[ 1 ];
		}
	}
}

// --------------------------------------------------------------- //

std::string ContentType::getParameter( const std::string &name ) const
{
	ParameterMap::const_iterator it = ct_parameters.find( boost::to_lower_copy( name ) );
	return it == ct_parameters.end() ? "" : it->second;
}

// --------------------------------------------------------------- //

std::string ContentType::toString() const
{
	return ct_type + "/" + ct_subtype;
}

// --------------------------------------------------------------- //

namespace kc_sf
{
	std::ostream &
	operator <<( std::ostream &out, const ContentType &ct )
	{
		out << ct.toString();
		return out;
	}
}

